package com.cumin.shiyin.core.config;

import com.cumin.shiyin.core.filter.XssFilter;
import com.cumin.shiyin.core.properties.CorsProperties;
import com.cumin.shiyin.core.properties.Knife4jProperties;
import com.cumin.shiyin.core.properties.XssProperties;
import com.cumin.shiyin.core.serializer.XssStringJsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Primary;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;


/**
 * @author YangJian.Kan
 * @version 1.0
 * @date 2020/4/12 21:58
 */
@Configuration
@ConditionalOnWebApplication
@EnableConfigurationProperties({CorsProperties.class, Knife4jProperties.class, XssProperties.class})
@EnableSwagger2
@EnableKnife4j
@Import(BeanValidatorPluginsConfiguration.class)
@AllArgsConstructor
public class CoreAutoConfiguration implements WebMvcConfigurer {

    private final CorsProperties corsProperties;

    private final Knife4jProperties knife4jProperties;

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/doc.html").addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");

    }

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping(corsProperties.getMappingUrl())
                .allowCredentials(corsProperties.getAllowCredentials())
                .allowedOrigins(corsProperties.getAllowOrigins())
                .allowedHeaders(corsProperties.getAllowHeaders())
                .allowedMethods(corsProperties.getAllowMethods());
    }

    @Bean
    @ConditionalOnProperty(prefix = "sy.core.xss", name = "enable", havingValue = "true")
    public FilterRegistrationBean<XssFilter> filterRegistrationBean(XssFilter xssFilter) {
        FilterRegistrationBean<XssFilter> registration = new FilterRegistrationBean<>();
        registration.setFilter(xssFilter);
        registration.addUrlPatterns("/*");
        registration.setName("xssFilter");
        return registration;
    }

    @Bean
    @ConditionalOnProperty(prefix = "sy.core.xss", name = "enable", havingValue = "true")
    public XssFilter xssFilter() {
        return new XssFilter();
    }

    @Bean
    public Docket defaultApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(new ApiInfoBuilder().title(knife4jProperties.getTitle())
                        .description(knife4jProperties.getDesc())
                        .termsOfServiceUrl(knife4jProperties.getServiceUrl())
                        .version(knife4jProperties.getVersion())
                        .contact(new Contact(knife4jProperties.getAuthor(), knife4jProperties.getAuthorUrl(), knife4jProperties.getAuthorContact()))
                        .build())
                //分组名称
                .groupName(knife4jProperties.getGroupName())
                .select()
                //这里指定Controller扫描包路径
                .apis(RequestHandlerSelectors.basePackage(knife4jProperties.getBasePackage()))
                .paths(PathSelectors.any())
                .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
                .build();
    }

    @Bean
    @Primary
    @ConditionalOnProperty(prefix = "sy.core.xss", name = "enable", havingValue = "true")
    public ObjectMapper xssObjectMapper(Jackson2ObjectMapperBuilder builder) {
        //解析器
        ObjectMapper objectMapper = builder.createXmlMapper(false).build();
        //注册xss解析器
        SimpleModule xssModule = new SimpleModule("XssStringJsonSerializer");
        xssModule.addSerializer(new XssStringJsonSerializer());
        objectMapper.registerModule(xssModule);
        //返回
        return objectMapper;
    }

}
